﻿using System;
using Plugins;
using Plugins.Base.Common;
using Plugins.UserControls;
using StockModel;
using TechnicalIndicators.DateBased;
using TechnicalIndicators.QuotationBased;
using Utils;

namespace SMAPlugin.Common
{
	internal class DecisionEngine : Plugins.Base.Common.DecisionEngineBase
	{
		#region Attributes

		private readonly HourSelectorData _hourSettings;
		private readonly StrategyControlData _strategySettings;

		private readonly MovingAverage _slowSMAGenerator;
		private readonly MovingAverage _fastSMAGenerator;

		private readonly LastValueGenerator _lastValueGenerator;

        private readonly IDecisionEngineStateProcessor _stateProcessor;

		#endregion

		#region Properties

		public new DecisionEngineData Data
		{
			get
			{
				return (DecisionEngineData)base.Data;
			}
		}

		#endregion

		#region Public Methods

		public DecisionEngine(DecisionEngineData data, ObservableCollection2<Quotation> quotationSource, StrategyControlData strategySettings, HourSelectorData hourSettings, OperationManager operationManager) : base(data, quotationSource, operationManager)
		{
			_strategySettings = strategySettings;
			_hourSettings = hourSettings;

			_lastValueGenerator = new LastValueGenerator();
			_lastValueGenerator.Configure(true);
			_lastValueGenerator.Source = new ReadWriteLockedObservableCollection<Quotation>(quotationSource, TimeSpan.FromSeconds(10));

			_slowSMAGenerator = new MovingAverage();
			_slowSMAGenerator.Configure(_strategySettings.SlowSMAPeriod);
			_slowSMAGenerator.Source = _lastValueGenerator.Serie;

			_fastSMAGenerator = new MovingAverage();
			_fastSMAGenerator.Configure(_strategySettings.FastSMAPeriod);
			_fastSMAGenerator.Source = _lastValueGenerator.Serie;

			_lastValueGenerator.Start();
			_slowSMAGenerator.Start();
			_fastSMAGenerator.Start();

			base.RegisterForNotifications();

			_stateProcessor = _strategySettings.WorkingMode == WorkingMode.LastFastCross ? new LastFastCrossProcessor(this.Data, _hourSettings, _slowSMAGenerator, _fastSMAGenerator, _lastValueGenerator, _strategySettings, base.OperationManager) : new FastSlowCrossProcessor(this.Data, _hourSettings, _slowSMAGenerator, _fastSMAGenerator, _lastValueGenerator, _strategySettings, base.OperationManager) as IDecisionEngineStateProcessor;
		}

		protected override void EvaluateStateMachineInternal()
		{
            this.SetState(this.Data.State);

			if (_lastValueGenerator.LastValue != null)
			{
				this.Data.PreviousLastValue = _lastValueGenerator.LastValue.Y;	
			}

			if (_fastSMAGenerator.LastValue != null)
			{
				this.Data.PreviousFastValue = _fastSMAGenerator.LastValue.Y;	
			}
		}

		#endregion

        #region Private Methods

        private void SetState(DecisionEngineStateBase state)
        {
            this.Data.State = state;

            DecisionEngineStateBase newState = null;

            if (state == DecisionEngineState.WaitingOpen)
            {
                newState = _stateProcessor.ProcessWaitingOpen();
            }
            else if (state == DecisionEngineState.WaitingSlowAverage)
            {
                newState = _stateProcessor.ProcessWaitingSlowAverage();
            }
            else if (state == DecisionEngineState.WaitingCrossUp)
            {
                newState = _stateProcessor.ProcessWaitingCrossUp();
            }
            else if (state == DecisionEngineState.WaitingCrossDown)
            {
                newState = _stateProcessor.ProcessWaitingCrossDown();
            }
            else if (state == DecisionEngineState.OnLongPossition)
            {
                newState = _stateProcessor.ProcessOnLongPossition();
            }
            else if (state == DecisionEngineState.OnShortPossition)
            {
                newState = _stateProcessor.ProcessOnShortPossition();
            }
            else if (state == DecisionEngineState.DayClosed)
            {
                newState = _stateProcessor.ProcessDayClosed();
            }

            if (newState != null)
            {
                this.SetState(newState);
            }
        }

        #endregion

    }
}
